package com.biotools.meerkat;

import java.text.*;

public class Action
{
    public static final int INVALID = -1;
    public static final int FOLD = 0;
    public static final int CHECK = 1;
    public static final int CALL = 2;
    public static final int BET = 3;
    public static final int RAISE = 4;
    public static final int SMALL_BLIND = 5;
    public static final int BIG_BLIND = 6;
    public static final int POST_BLIND = 7;
    public static final int ALLIN_PASS = 8;
    public static final int MUCK = 9;
    public static final int POST_ANTE = 10;
    public static final int SIT_OUT = 11;
    public static final int POST_DEAD_BLIND = 12;
    private int type;
    private double amount;
    private double toCall;
    private static final DecimalFormat dollarsCents;
    private static final DecimalFormat dollars;
    
    static {
        dollarsCents = new DecimalFormat(Messages.getString("Action.DollarFormatWithCents"));
        dollars = new DecimalFormat(Messages.getString("Action.DollarFormat"));
    }
    
    public Action(final int type, final double toCall, final double amount) {
        super();
        this.type = -1;
        this.amount = 0.0;
        this.toCall = 0.0;
        this.type = type;
        this.amount = this.roundToCents(amount);
        this.toCall = this.roundToCents(toCall);
    }
    
    public boolean equivalent(final Action a) {
        return this.type == a.type && this.amount == a.amount && this.toCall == a.toCall;
    }
    
    public double getAmount() {
        return this.amount;
    }
    
    public double getToCall() {
        return this.toCall;
    }
    
    public int getType() {
        return this.type;
    }
    
    public static Action postAnte(final double toPost) {
        return new Action(10, 0.0, toPost);
    }
    
    public static Action sitout() {
        return new Action(11, 0.0, 0.0);
    }
    
    public static Action postBlindAction(final double toPost) {
        return new Action(7, 0.0, toPost);
    }
    
    public static Action postDeadBlindAction(final double toPost) {
        return new Action(12, 0.0, toPost);
    }
    
    public static Action smallBlindAction(final double toPost) {
        return new Action(5, 0.0, toPost);
    }
    
    public static Action bigBlindAction(final double toPost) {
        return new Action(6, 0.0, toPost);
    }
    
    public static Action foldAction(final GameInfo gi) {
        return foldAction(gi.getAmountToCall(gi.getCurrentPlayerSeat()));
    }
    
    public static Action foldAction(final double toCall) {
        return new Action(0, toCall, 0.0);
    }
    
    public static Action checkOrFoldAction(final GameInfo gi) {
        return checkOrFoldAction(gi.getAmountToCall(gi.getCurrentPlayerSeat()));
    }
    
    public static Action checkOrFoldAction(final double toCall) {
        if (toCall > 0.0) {
            return new Action(0, toCall, 0.0);
        }
        return checkAction();
    }
    
    public static Action muckAction() {
        return new Action(9, 0.0, 0.0);
    }
    
    public static Action checkAction() {
        return new Action(1, 0.0, 0.0);
    }
    
    public static Action callAction(final GameInfo gi) {
        return callAction(gi.getAmountToCall(gi.getCurrentPlayerSeat()));
    }
    
    public static Action callAction(final double toCall) {
        if (toCall == 0.0) {
            return checkAction();
        }
        return new Action(2, toCall, 0.0);
    }
    
    public static Action betAction(final GameInfo gi) {
        return betAction(gi.getMinRaise());
    }
    
    public static Action betAction(final double amountToRaise) {
        return new Action(3, 0.0, amountToRaise);
    }
    
    public static Action raiseAction(final GameInfo gi) {
        return raiseAction(gi, gi.getMinRaise());
    }
    
    public static Action raiseAction(final GameInfo gi, final double amountToRaise) {
        return raiseAction(gi.getAmountToCall(gi.getCurrentPlayerSeat()), amountToRaise);
    }
    
    public static Action raiseAction(final double toCall, final double amountToRaise) {
        if (amountToRaise <= 0.0) {
            return callAction(toCall);
        }
        if (toCall == 0.0) {
            return betAction(amountToRaise);
        }
        return new Action(4, toCall, amountToRaise);
    }
    
    public static Action allInPassAction() {
        return new Action(8, 0.0, 0.0);
    }
    
    public boolean isFold() {
        return this.type == 0;
    }
    
    public boolean isFoldOrMuck() {
        return this.type == 0 || this.type == 9;
    }
    
    public boolean isCheck() {
        return this.type == 1;
    }
    
    public boolean isCall() {
        return this.type == 2;
    }
    
    public boolean isCheckOrCall() {
        return this.type == 2 || this.type == 1;
    }
    
    public boolean isBet() {
        return this.type == 3;
    }
    
    public boolean isRaise() {
        return this.type == 4;
    }
    
    public boolean isBetOrRaise() {
        return this.type == 3 || this.type == 4;
    }
    
    public boolean isBlind() {
        return this.type == 5 || this.type == 6 || this.type == 7 || this.type == 12;
    }
    
    public boolean isPost() {
        return this.type == 7 || this.type == 12;
    }
    
    public boolean isPostDeadBlind() {
        return this.type == 12;
    }
    
    public boolean isSmallBlind() {
        return this.type == 5;
    }
    
    public boolean isBigBlind() {
        return this.type == 6;
    }
    
    public boolean isAllInPass() {
        return this.type == 8;
    }
    
    public boolean isSitout() {
        return this.type == 11;
    }
    
    public boolean isMuck() {
        return this.type == 9;
    }
    
    public boolean isAnte() {
        return this.type == 10;
    }
    
    public int getActionIndex() {
        switch (this.type) {
            case 0: {
                return 0;
            }
            case 1: {
                return 1;
            }
            case 2: {
                return 1;
            }
            case 3: {
                return 2;
            }
            case 4: {
                return 2;
            }
            default: {
                return -1;
            }
        }
    }
    
    public static Action getAction(final int a, final double toCall, final double amount) {
        switch (a) {
            case 0: {
                return checkOrFoldAction(toCall);
            }
            case 1: {
                return callAction(toCall);
            }
            case 2: {
                return raiseAction(toCall, amount);
            }
            default: {
                return null;
            }
        }
    }
    
    public String toString() {
        final Object[] msgArgsAmount = { formatCash(this.amount) };
        switch (this.type) {
            case 5: {
                return Messages.getString("Action.BlindPattern", msgArgsAmount);
            }
            case 6: {
                return Messages.getString("Action.BlindPattern", msgArgsAmount);
            }
            case 7: {
                return Messages.getString("Action.PostPattern", msgArgsAmount);
            }
            case 12: {
                return Messages.getString("Action.PostDeadPattern", msgArgsAmount);
            }
            case 10: {
                return Messages.getString("Action.AntePattern", msgArgsAmount);
            }
            case 0: {
                return Messages.getString("Action.Fold");
            }
            case 9: {
                return Messages.getString("Action.Muck");
            }
            case 1: {
                return Messages.getString("Action.Check");
            }
            case 2: {
                final Object[] msgArgs = { formatCash(this.toCall) };
                return Messages.getString("Action.CallPattern", msgArgs);
            }
            case 3: {
                return Messages.getString("Action.BetPattern", msgArgsAmount);
            }
            case 4: {
                return Messages.getString("Action.RaisePattern", msgArgsAmount);
            }
            case 8: {
                return Messages.getString("Action.AllIn");
            }
            case 11: {
                return Messages.getString("Action.SitsOut");
            }
            default: {
                return Messages.getString("Action.12");
            }
        }
    }
    
    public String toString2() {
        final Object[] msgArgsAmount = { formatCash(this.amount) };
        switch (this.type) {
            case 5: {
                return Messages.getString("Action.SmallBlindLongPattern", msgArgsAmount);
            }
            case 6: {
                return Messages.getString("Action.BigBlindLongPattern", msgArgsAmount);
            }
            case 7: {
                return Messages.getString("Action.BlindLongPattern", msgArgsAmount);
            }
            case 12: {
                return Messages.getString("Action.PostDeadLongPattern", msgArgsAmount);
            }
            case 10: {
                return Messages.getString("Action.AnteLongPattern", msgArgsAmount);
            }
            case 0: {
                return Messages.getString("Action.FoldLong");
            }
            case 9: {
                return Messages.getString("Action.MuckLong");
            }
            case 1: {
                return Messages.getString("Action.CheckLong");
            }
            case 2: {
                final Object[] msgArgs = { formatCash(this.toCall) };
                return Messages.getString("Action.CallLongPattern", msgArgs);
            }
            case 3: {
                return Messages.getString("Action.BetLongPattern", msgArgsAmount);
            }
            case 4: {
                return Messages.getString("Action.RaiseLongPattern", msgArgsAmount);
            }
            case 8: {
                return Messages.getString("Action.AllInLong");
            }
            case 11: {
                return Messages.getString("Action.SitOutLong");
            }
            default: {
                return "";
            }
        }
    }
    
    public static String formatCash(final double value) {
        if (value == (int)value) {
            return Action.dollars.format(value);
        }
        return Action.dollarsCents.format(value);
    }
    
    public static String formatCashFull(final double value) {
        return Action.dollarsCents.format(value);
    }
    
    public boolean isVoluntary() {
        return !this.isAnte() && !this.isAllInPass() && !this.isBlind();
    }
    
    private double roundToCents(final double v) {
        return Math.round(v * 100.0) / 100.0;
    }
}
